package com.ddwl.gate.service;


import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.ddwl.common.util.BeanConverUtils;
import com.ddwl.gate.mapper.RegionMapper;
import com.ddwl.gate.model.Region;
import com.ddwl.schema.bo.gate.RegionBo;
import com.ddwl.schema.vo.gate.RegionVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestTemplate;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author Fu Zhaohui
 * @date 2017/1/3
 */
@Slf4j
@Service
public class RegionService {

    @Autowired
    private RegionMapper regionMapper;
    @Autowired
    private RestTemplate restTemplate;
    @Value("${amap.key}")
    private String amapKey;
    @Value("${amap.url}")
    private String amapUrl;
    @Value("${amap.urlForLocation}")
    private String urlForLocation;

    public RegionVo getRegionById(String regionId){
        return BeanConverUtils.convertBean(regionMapper.findByPk(regionId),RegionVo.class);
    }

    public List<RegionVo> listByIds(String ids) {
        if (StrUtil.isEmpty(ids)) {
            return new ArrayList<>();
        }
        List<String> list = Arrays.asList(ids.split(","));
        return BeanConverUtils.convertBeanList(regionMapper.findByPks(list), RegionVo.class);
    }

    public List<RegionVo> getRegion(String province, String city, String keyword) {
        List<Region> entities;
        if (StringUtils.hasText(keyword)) {
            entities = regionMapper.findByKeyword(keyword);
        } else {
            entities = regionMapper.findByProvinceAndCity(province, city);
        }
        return entities.stream().map(entity -> {
            RegionVo vo = new RegionVo();
            BeanUtils.copyProperties(entity, vo);
            return vo;
        }).collect(Collectors.toList());
    }

    public List<RegionVo> getAllRegion() {
        List<Region> entities = regionMapper.findAll();
        List<RegionVo> vos = new ArrayList<>();
        Map<String, RegionVo> regionMap = new HashMap<>();
        entities.forEach(entity -> {
            String district = entity.getDistrict();
            RegionVo vo = new RegionVo();
            vo.setId(entity.getId());
            if (!StringUtils.hasText(district)) {
                String city = entity.getCity();
                regionMap.put(entity.getId(), vo);
                if (!StringUtils.hasText(city)) {
                    vo.setProvince(entity.getProvince());
                    vo.setProvinceName(entity.getProvinceName());
                    vo.setCities(new ArrayList<>());
                    vos.add(vo);
                } else {
                    vo.setCity(entity.getCity());
                    vo.setCityName(entity.getCityName());
                    vo.setDistricts(new ArrayList<>(0));
                    regionMap.get(entity.getProvince()).getCities().add(vo);
                }
            } else {
                vo.setDistrict(entity.getDistrict());
                vo.setDistrictName(entity.getDistrictName());
                if (entity.getProvince().equals(entity.getCity())) {
                    RegionVo vo1 = regionMap.get(String.format("%s-%s", entity.getProvince(), entity.getCity()));
                    if (vo1 == null) {
                        vo1 = new RegionVo();
                        vo1.setCity(entity.getCity());
                        vo1.setCityName(entity.getCityName());
                        vo1.setDistricts(new ArrayList<>(0));
                        regionMap.put(String.format("%s-%s", entity.getProvince(), entity.getCity()), vo1);
                    }
                    vo1.getDistricts().add(vo);
                } else {
                    regionMap.get(entity.getCity()).getDistricts().add(vo);
                }
            }
        });
        return vos;
    }

    public List<RegionVo> findDistrictByCityName(String cityName) {
        if (!StringUtils.hasText(cityName)) {
            return null;
        }
        List<Region> regions = regionMapper.findDistrictByCityName(cityName);
        return BeanConverUtils.convertBeanList(regions, RegionVo.class);
    }

    public Object geoLoc(String city, String address) {
        String result = restTemplate.getForObject(amapUrl, String.class, address, city, amapKey);
        JSONObject obj = JSONObject.parseObject(result);
        if ("1".equals(obj.getString("status"))) {
            return obj.getJSONArray("geocodes");
        } else {
            return null;
        }
    }

    public Object geoReLoc(Integer radius,String location) {
        String result = restTemplate.getForObject(urlForLocation, String.class, location, amapKey, radius);
        JSONObject obj = JSONObject.parseObject(result);
        if ("1".equals(obj.getString("status"))) {
            return obj.getJSONObject("regeocode");
        } else {
            return null;
        }
    }

    public String getCityId(String provinceName, String cityName) {
        return regionMapper.findCityId(provinceName, cityName);
    }

    public String getAmapKey() {
        return amapKey;
    }


    public RegionVo findByBo(RegionBo regionBo) {
        Region region=regionMapper.findByBo(regionBo);
        if(null!=region){
            RegionVo vo = new RegionVo();
            BeanUtils.copyProperties(region, vo);
            return vo;
        }
        return null;
    }

    /**
     * 百度地图转高德地图
     *
     */
    public double[] baidu2AMap(double lat, double lon) {
        try {
            if (lat != 0 && lon != 0) {
                double var4 = 0.006401062D;
                double var6 = 0.0060424805D;
                double[] var2 = null;

                for (int var3 = 0; var3 < 2; ++var3) {
                    var2 = new double[2];
                    double var16 = lon - var4;
                    double var18 = lat - var6;
                    double[] var29 = new double[2];
                    double var24 = Math.cos(b(var16) + Math.atan2(var18, var16)) * (a(var18) + Math.sqrt(var16 * var16 + var18 * var18)) + 0.0065D;
                    double var26 = Math.sin(b(var16) + Math.atan2(var18, var16)) * (a(var18) + Math.sqrt(var16 * var16 + var18 * var18)) + 0.006D;
                    var29[1] = (c(var24));
                    var29[0] = (c(var26));
                    var2[1] = (c(lon + var16 - var29[1]));
                    var2[0] = (c(lat + var18 - var29[0]));
                    var4 = lon - var2[1];
                    var6 = lat - var2[0];
                }

                return var2;
            }
        } catch (Throwable var28) {
            // ll.a(var28, "OffsetUtil", "B2G");
        }

        return new double[]{lat, lon};
    }

    private static double a = 3.141592653589793D;

    private static double a(double var0) {
        return Math.sin(var0 * 3000.0D * (a / 180.0D)) * 2.0E-5D;
    }

    private static double b(double var0) {
        return Math.cos(var0 * 3000.0D * (a / 180.0D)) * 3.0E-6D;
    }

    private static double c(double var0) {
        return (new BigDecimal(var0)).setScale(8, 4).doubleValue();
    }

}
